<template>
  <el-dialog title="设置权限" :model-value="visible" :before-close="setVisible">
    <el-tree
      ref="treeRef"
      accordion
      show-checkbox
      node-key="id"
      :data="roots"
      :expand-on-click-node="false"
      style="padding: 20px">
      <template #default="{ data }">
        <span>{{ data.code }}&nbsp;&nbsp;&nbsp;&nbsp;{{ data.remark }}&nbsp;&nbsp;&nbsp;&nbsp;</span>
      </template>
    </el-tree>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="setVisible">取 消</el-button>
        <el-button type="primary" @click="handleUpdate">确 定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts">
  import { defineComponent, nextTick, PropType, ref } from 'vue';
  import { useAuthority } from '@/views/system/hooks/useAuthority';
  import { User } from '@/services/authorization/User';
  import { UserAccess, userAccessService } from '@/services/authorization/UserAccess';
  import { HttpUtil } from '@/utils/HttpUtil';
  import { ElMessage } from 'element-plus';
  import { Access, accessService } from '@/services/authorization/Access';
  import { ELTree } from '@/utils/types';
  import { difference, intersection } from 'lodash';
  import { notEmpty } from '@/utils/General';

  export default defineComponent({
    name: 'AuthorityDialog',
    props: {
      current: Object as PropType<User | null>,
      visible: {
        type: Boolean,
        required: true,
      },
      setVisible: {
        type: Function,
        required: true,
      },
    },
    setup: prop => {
      const { select, roots } = useAuthority();
      // watch(prop.current, (o, n) => {
      //   console.log(o, n);
      // });
      const userAuthorities = ref([] as UserAccess[]);
      const authorityIds = ref([] as string[]);

      const treeRef = ref(null as ELTree | null);

      const selectByUserId = async (userId?: string) => {
        try {
          const userAccessResp = await userAccessService.select({
            query: {
              userId,
            },
          });
          if (HttpUtil.isOk(userAccessResp)) {
            userAuthorities.value = HttpUtil.getList(userAccessResp);
            const accessResp = await accessService.selectByIds(
              userAuthorities.value.map(v => v.accessId),
              false
            );
            if (HttpUtil.isOk(accessResp)) {
              authorityIds.value = HttpUtil.getData(accessResp).map(v => v.id);
              // console.log(this.authorityIds);
              treeRef.value?.setCheckedKeys(authorityIds.value);
            } else if (HttpUtil.isNoContent(accessResp)) {
              userAuthorities.value = [];
              authorityIds.value = [];
              treeRef.value?.setCheckedKeys(authorityIds.value);
            }
          }
        } catch (e) {
          userAuthorities.value = [];
          authorityIds.value = [];
          treeRef.value?.setCheckedKeys(authorityIds.value);
        }
      };

      const handleUpdate = async () => {
        // console.log(treeRef);
        const checkedIds = (treeRef.value?.getCheckedNodes() as Access[]).map(v => v.id);
        // console.log(authorityIds, checkedIds);
        const temp = intersection(checkedIds, authorityIds.value);
        // console.log(temp);
        try {
          const insertIds = difference(checkedIds, temp);
          console.log(insertIds);
          if (notEmpty(insertIds)) {
            const insertList = insertIds.map(
              v =>
                ({
                  userId: prop.current?.id,
                  accessId: v,
                } as UserAccess)
            );
            const insertResp = await userAccessService.insertList(insertList);
            if (!HttpUtil.isCreated(insertResp)) {
              throw new Error('权限修改失败！');
            }
          }
          const accessDeleteIds = difference(authorityIds.value, temp);
          const deleteIds = userAuthorities.value.filter(v => accessDeleteIds.includes(v.accessId)).map(v => v.id);
          console.log(deleteIds);
          if (notEmpty(deleteIds)) {
            const deleteResp = await userAccessService.deleteByIds(deleteIds);
            if (!HttpUtil.isNoContent(deleteResp)) {
              throw new Error('权限修改失败！');
            }
          }
          if (notEmpty(insertIds) || notEmpty(deleteIds)) {
            ElMessage.success('权限修改成功！');
          }
        } catch (e) {
          ElMessage.error((e as Error).message);
        } finally {
          prop.setVisible();
          await selectByUserId(prop.current?.id);
        }
      };
      return {
        select,
        roots,
        userAuthorities,
        authorityIds,
        treeRef,
        selectByUserId,
        handleUpdate,
      };
    },
    watch: {
      // async current(n: User, o: User) {
      async current(n: User) {
        // console.log(o, n);
        if (n) {
          try {
            // eslint-disable-next-line vue/valid-next-tick
            await nextTick(async () => {
              await this.selectByUserId(n.id);
            });
            // eslint-disable-next-line no-empty
          } catch (e) {}
        } else {
          this.userAuthorities = [];
          this.authorityIds = [];
        }
      },
    },
  });
</script>

<style scoped></style>
